import { computed, observable } from 'mobx';
import moment from 'moment';

import { defaultDate, defaultDateStr, defaultTimeFormatter } from 'Configs/common';

export type WithCommonDataAttributeForm = Partial<
    Pick<WithCommonModel, WithCommonModelIndex.NAME | WithCommonModelIndex.DESCRIPTION>
>;

export const enum WithCommonModelIndex {
    ID = 'id',
    NAME = 'name',
    DESCRIPTION = 'desc',
    CREATE_TIME = 'createTime',
    CREATE_TIMESTAMP = 'createTimestamp',
    CREATE_USER = 'createUser',
    CREATE_USER_NAME = 'createUserName',
    UPDATE_TIME = 'updateTime',
    UPDATE_TIMESTAMP = 'updateTimestamp',
    UPDATE_USER = 'updateUser',
    UPDATE_USER_NAME = 'updateUserName',
}

export interface WithCommonDataStructure {
    [WithCommonModelIndex.ID]?: SysId;
    [WithCommonModelIndex.NAME]?: SysName;
    [WithCommonModelIndex.DESCRIPTION]?: SysDescription;
    [WithCommonModelIndex.CREATE_TIME]?: SysTimestamp;
    [WithCommonModelIndex.CREATE_USER]?: SysId;
    [WithCommonModelIndex.CREATE_USER_NAME]?: SysUser;
    [WithCommonModelIndex.UPDATE_TIME]?: SysTimestamp;
    [WithCommonModelIndex.UPDATE_USER]?: SysId;
    [WithCommonModelIndex.UPDATE_USER_NAME]?: SysUser;
}
/**
 * `wrapper class` for the model with common data
 * @props id `id` of the specific data structure
 * @props name `name` of the specific data structure
 * @props desc `desc` for the specific data structure
 * @props createTime `createTime` for the specific data structure
 * @props updateTime `updateTime` for the specific data structure
 * @return `Class WithCommonModel`
 */
class WithCommonModel {
    @observable id?: SysId = undefined;

    @observable name?: SysName = undefined;

    @observable desc?: SysDescription = undefined;

    protected createTimestamp?: SysTimestamp = defaultDate;

    protected createTimestampDsl?: SysTimestampDsl = defaultDateStr;

    set createTime(data: SysTime | undefined) {
        this.createTimestamp = data ?? defaultDate;
        if (data) this.createTimestampDsl = moment(data).format(defaultTimeFormatter);
    }

    @computed get createTime() {
        return this.createTimestampDsl ?? defaultDateStr;
    }

    @observable createUser?: SysId = undefined;

    @observable createUserName?: SysName = undefined;

    protected updateTimestamp?: SysTimestamp = defaultDate;

    protected updateTimestampDsl?: SysTimestampDsl = defaultDateStr;

    set updateTime(data: SysTime | undefined) {
        this.updateTimestamp = data ?? defaultDate;
        if (data) this.updateTimestampDsl = moment(data).format(defaultTimeFormatter);
    }

    @computed get updateTime() {
        return this.updateTimestampDsl ?? defaultDateStr;
    }

    @observable updateUser?: SysId = undefined;

    @observable updateUserName?: SysName = undefined;

    constructor(data: WithCommonDataStructure) {
        this.id = data.id ?? undefined;
        this.name = data.name ?? undefined;
        this.desc = data.desc ?? undefined;

        this.createTime = data.createTime ?? defaultDate;
        this.createUser = data.createUser ?? undefined;
        this.createUserName = data.createUserName ?? undefined;
        this.updateTime = data.updateTime ?? defaultDate;
        this.updateUser = data.updateUser ?? undefined;
        this.updateUserName = data.updateUserName ?? undefined;
    }
}

export default WithCommonModel;
